
#include "typeAttack.h"
#include "Entities/actor.h"
#include "Game/Game.h"
#include "event.h"

namespace skill {
    bool HurtBuff::use(Game *g, const std::vector<std::string> &params) {
        if (!Buff::use(g, params)) return false;
        if (++HurtTimer % HurtCD != 0)
            return true;
        try {
            int damage = Hurt;
            int now_hp = std::stoi(origin->properties["hp"]);
            now_hp -= damage;
            origin->properties["hp"] = std::to_string(now_hp);
            return true;
        } catch (std::exception) {
            return false;
        }
    }
    bool ScourgeBuff::use(Game *g, const std::vector<std::string> &params)
    {
        if(!HurtBuff::use(g, params)) return false;
        if(!this->hasPrefix(origin->id))
        {
            this->prefix += origin->id + "_";   //避免回传，进行记录
        }
        if(++ScourgeTimer % ScourgeT == 0)  //传播
        {
            try{
                std::map<std::string, Entity*> entityList = g->entityManager.entityList;
                for(auto it = entityList.begin(); it != entityList.end(); ++it)
                {
                    if(!it->second->hasPrefix("_Actor_")) continue;
                    Actor *targetActor = dynamic_cast<Actor *>(it->second);
                    if(origin->properties["link_out"].find("|" + targetActor->id + "|") == std::string::npos &&
                            targetActor->properties["link_out"].find("|" + origin->id + "|") == std::string::npos) continue;
                    if(this->prefix.find(targetActor->id) != std::string::npos) continue;
                    this->prefix += targetActor->id;
                    ScourgeBuff* scourgebuff = new ScourgeBuff(ScourgeT, Hurt, HurtCD, remaining);
                    scourgebuff->prefix = this->prefix;
                    targetActor->learnSkill(scourgebuff);
                    if (!origin->hasSkill("SpreadScourge")) origin->learnSkill(new skill::SpreadScourge);
                    origin->useLater("SpreadScourge", {targetActor->id});
                }
                return true;
            }catch(std::exception){
                return false;
            }
        }
        return true;
    }
    bool Scourge::canUse(Game *g, const std::vector<std::string> &params) {
        if(!CoolDownSkill::canUse(g, params)) return false;
        if(params.size() < 1) return false;

        if(!origin->hasPrefix("_Actor")) return false;
        Entity* target = g->entityManager.findEntityByID(params[0]);
        if(target == nullptr) return false;
        if(!target->hasPrefix("_Actor_")) return false;

        Actor* originActor = dynamic_cast<Actor*>(origin);
        Actor* targetActor = dynamic_cast<Actor*>(target);
        if(originActor->squaredDistanceTo(targetActor) > this->range()) return false;

        try{
            std::stoi(target->properties["hp"]);
        }catch (std::exception){
            return false;
        }
        return true;
    }

    bool Scourge::use(Game *g, const std::vector<std::string> &params) {
        if (!CoolDownSkill::use(g, params)) return false;
        try{
            Actor *sender = dynamic_cast<Actor*>(origin);
            Actor *target = dynamic_cast<Actor*>(g->entityManager.findEntityByID(params[0]));
            target->learnSkill(new ScourgeBuff(ScourgeTimer, sender->getDamage(target, ScourgeDamage), ScourgeHurtCD, ScourgeRemainTime));
            return true;
        }catch(std::exception){
            return false;
        }
    }

    bool Bombing::canUse(Game *g, const std::vector<std::string> &params) {
        if(!CoolDownSkill::canUse(g, params)) return false;
        if(params.size() < 2) return false;

        if(!origin->hasPrefix("_Actor_")) return false;
        //这里还应该判断目标点是否在地图范围内

        Actor *originActor = dynamic_cast<Actor *>(origin);
        int x = std::stoi(params[0]);
        int y = std::stoi(params[1]);
        Point center(x, y);
        if(getSquaredEuclideanDist(originActor->pos(), center) > this->range()) return false;

        std::map<std::string, Entity*> entityList = g->entityManager.entityList;
        for(auto it = entityList.begin(); it != entityList.end(); ++it)
        {
            if(!it->second->hasPrefix("_Actor_")) continue;
            Actor *targetActor = dynamic_cast<Actor *>(it->second);
            if((targetActor->pos() - center).getSquaredEuclideanLength() > BombingRadius) continue;

            try{
                std::stoi(targetActor->properties["hp"]);
            }catch(std::exception){
                return false;
            }
        }
        return true;
    }

    bool Bombing::use(Game *g, const std::vector<std::string> &params) {
        if(!CoolDownSkill::use(g, params)) return false;
        try{
            int x = std::stoi(params[0]);
            int y = std::stoi(params[1]);
            Point center(x, y);
            std::map<std::string, Entity*> entityList = g->entityManager.entityList;
            for(auto it = entityList.begin(); it != entityList.end(); ++it)
            {
                if(!it->second->hasPrefix("_Actor_")) continue;
                Actor *targetActor = dynamic_cast<Actor *>(it->second);
                if ((targetActor->pos() - center).getSquaredEuclideanLength() > BombingRadius) continue;
                (dynamic_cast<Actor*>(origin))->projectDamage(targetActor, BombingDamage);
            }
            return true;
        }catch(std::exception){
            return false;
        }
    }


    }